/**
 * Sample Skeleton for "Leave.fxml" Controller Class
 * You can copy and paste this code into your favorite IDE
 **/

package com.pentofab.payrollmanagement.ui.controller;

import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.Callback;

import com.pentofab.payrollmanagement.application.PayrollApplicationFactory;
import com.pentofab.payrollmanagement.dao.EmployeeDao;
import com.pentofab.payrollmanagement.dao.LeaveDAO;
import com.pentofab.payrollmanagement.dao.model.AttendanceDetail;
import com.pentofab.payrollmanagement.dao.model.Company;
import com.pentofab.payrollmanagement.dao.model.Employee;
import com.pentofab.payrollmanagement.dao.model.Leave;
import com.pentofab.payrollmanagement.dao.model.LeaveDetail;
import com.pentofab.payrollmanagement.dao.model.UserAccounts;
import com.pentofab.payrollmanagement.exception.BusinessException;
import com.pentofab.payrollmanagement.utilities.PayRollUtility;

public class LeaveModuleController extends AbstractUIController implements
		Initializable, FormValidator {

	@FXML
	Parent root;
	@FXML
	private TableView<LeaveDetail> LeaveTable;
//	@FXML
//	private TableColumn<LeaveDetail, String> Select;
	@FXML
	private TableColumn<LeaveDetail, String> FROM_DATE;
	@FXML
	private TableColumn<LeaveDetail, String> TO_DATE;
	@FXML
	private TableColumn<LeaveDetail, String> number;
	@FXML
	private TableColumn<LeaveDetail, String> Reason;
	@FXML
	private TableColumn<LeaveDetail, String> LEAVE_TYPE;
	@FXML
	private TextField employeeIDField;
	@FXML
	private TextField employeeNameField;
	@FXML
	private ChoiceBox<String> from_date;
	@FXML
	private ChoiceBox<String> from_month;
	@FXML
	private ChoiceBox<String> from_year;
	@FXML
	private ChoiceBox<String> leaveTypeBox;
	@FXML
	private TextField noOfDays;
	@FXML
	private ChoiceBox<String> to_date;
	@FXML
	private ChoiceBox<String> to_month;
	@FXML
	private ChoiceBox<String> to_year;
	@FXML
	private TextArea reasonForLeave;
	/*@FXML
	private TextField balanceCount;*/
	@FXML
	private CheckBox fromHalfDay;
	@FXML
	private CheckBox toHalfDay;
	@FXML
    private Button save;
	@FXML
	private Label leaveDetailId;

	private EmployeeDao employeeMgmt = PayrollApplicationFactory.getEmployeeMgmt();
	private LeaveDAO leaveDAO = PayrollApplicationFactory.getLeaveDAO();
	private ArrayList<String> yearList = new ArrayList<String>();
	private ArrayList<String> fromMonthDaysList = new ArrayList<String>();
	private ArrayList<String> toMonthDaysList = new ArrayList<String>();
	private Employee employee = null;
	int fromMaxDay;
	int toMaxDay;
	String fromDate = null;
	String toDate = null;
	final private ObservableList<LeaveDetail> data = FXCollections.observableArrayList();
	private Company company;
	private UserAccounts userAccounts;

	@Override
	public Parent getView() {
		return root;
	}

	@Override
	public String getTitle() {
		return UIMessages.UITitles.Leave_FORM;
	}

	public void goBack() {

		if (getParent() != null && getParent().length() > 0) {
			PayrollApplicationFactory.getMainController().showScreen(
					getParent(), false);
		}
	
	}

	public void reset(ActionEvent event) {

		refreshUI();
	}

	public void save() {

		try {
			if (!validEmpId()) {
				return;
			}
			String validationMSG = getValidationMessage();
			if (!validationMSG.equals("")) {
				showError(validationMSG);
				moveFocusToComp(employeeIDField);
				return;
			}
			Leave leaveObject = new Leave();
			leaveObject.setEmployee(employee);
			String leaveType = leaveTypeBox.getSelectionModel()
					.getSelectedItem();
			leaveObject.setLeaveType(leaveType.substring(0,
					leaveType.lastIndexOf(":")).trim());
			
			leaveObject.setFromDate(fromDate);
			leaveObject.setToDate(toDate);
			
			if (!noOfDays.getText().trim().equals("")) {
				leaveObject.setNoOfDays(new Double(noOfDays.getText()));
			}
			if (!noOfDays.getText().trim().equals(""))
				leaveObject.setAvaiblebleDays(new Double(noOfDays.getText()));
			leaveObject.setApprover(userAccounts.getUsername());
			leaveObject.setReson(reasonForLeave.getText());
			String halfDay = "00";
			if(fromHalfDay.isSelected() && toHalfDay.isSelected())
				halfDay = "11";
			else if(fromHalfDay.isSelected())
				halfDay = "10";
			else if(toHalfDay.isSelected())
				halfDay = "01";
			leaveObject.setHalfDay(halfDay);
			leaveDAO.applyforLeave(leaveObject);
			populateLeaveTable(employee.getEmpId());
			save.setDisable(true);
		
		} catch (Exception e) {

			e.printStackTrace();
			showError(e.getMessage());
//			moveFocusToComp(employeeIDField);
			return;
		}

		showInfo(UIMessages.APPLIED_LEAVE_SUCCESSFULLY);
	}

	public void delete(ActionEvent event) {
		
		if( LeaveTable.getSelectionModel().getSelectedIndex() < 0){
			showError(UIMessages.SELECT_ROW_TO_DELETE);
			return;
		}
		
		LeaveDetail leaveDetail = LeaveTable.getSelectionModel().getSelectedItem();
		 if(showConfirmDialog(UIMessages.CONFIRM_DELETE)){
			 try {
				 leaveDAO.deleteLeave(employeeIDField.getText(),leaveDetail.getFROM_DATE(),leaveDetail.getTO_DATE());
				showInfo(UIMessages.LEAVE_CANCELLED);
				populateLeaveTable(employee.getEmpId());
			} catch (BusinessException e) {
				System.out.println(e.getMessage());
				showError(e.getMessage());
				moveFocusToComp(LeaveTable);
			}
		 }
	}

	@Override
	public boolean isValid() {

		if (employeeIDField.getText().length() < 6) {
			return false;
		}
		if (leaveTypeBox.getSelectionModel().getSelectedIndex() < 0) {
			return false;
		}
		return true;
	}

	@Override
	public String getValidationMessage() {

		if (leaveTypeBox.getSelectionModel().getSelectedIndex() < 0) {
			return UIMessages.LEAVE_TYPE;
		}
		if (from_year.getSelectionModel().getSelectedIndex() < 0) {
			return UIMessages.FROM_YEAR;
		}
		if (from_month.getSelectionModel().getSelectedIndex() < 0) {
			return UIMessages.FROM_MONTH;
		}
		if (from_date.getSelectionModel().getSelectedIndex() < 0) {
			return UIMessages.FROM_DAY;
		}
		if (to_year.getSelectionModel().getSelectedIndex() < 0) {
			return UIMessages.TO_YEAR;
		}
		if (to_month.getSelectionModel().getSelectedIndex() < 0) {
			return UIMessages.TO_MONTH;
		}
		if (to_date.getSelectionModel().getSelectedIndex() < 0) {
			return UIMessages.TO_DAY;
		}

		if (reasonForLeave.getText().trim().equals("")) {
			return UIMessages.LEAVE_REASON;
		}

		if (!noOfDays.getText().trim().equals("")) {
			float noOfdays = new Float(noOfDays.getText().trim());
		}
		return "";

	}

	@Override
	public void refreshUI(Object... args) {

		if (args != null && args.length > 0) {
			Company company = (Company) args[0];
			this.company = company;
			
			if(args.length > 1 && args[1] instanceof UserAccounts){
				userAccounts = (UserAccounts) args[1];
			}
		}
		
		employeeIDField.clear();
		employeeNameField.clear();
		leaveTypeBox.getSelectionModel().clearSelection();
		from_year.getItems().removeAll(yearList);
		to_year.getItems().removeAll(yearList);
		yearList.clear();
		int year = PayRollUtility.getYear() - 1;
		for (int i = 0; i < 5; i++) {
			yearList.add(year + "");
			year++;
		}
		year = PayRollUtility.getYear();
		from_year.getItems().addAll(yearList);
		to_year.getItems().addAll(yearList);
		from_year.getSelectionModel().select(String.valueOf(year));
		to_year.getSelectionModel().select(String.valueOf(year));
		from_month.getSelectionModel().clearSelection();
		to_month.getSelectionModel().clearSelection();
		from_date.getSelectionModel().clearSelection();
		to_date.getSelectionModel().clearSelection();
		noOfDays.clear();
		LeaveTable.getItems().removeAll(LeaveTable.getItems());
		reasonForLeave.clear();
		leaveDetailId.setText("");
		employee = null;
		moveFocusToComp(employeeIDField);
		fromHalfDay.setSelected(false);
		toHalfDay.setSelected(false);
		save.setDisable(false);

	}

	public void eidLableFocusHandler() {

		employeeIDField.focusedProperty().addListener(
				new ChangeListener<Boolean>() {
					@Override
					public void changed(ObservableValue<? extends Boolean> ov,
							Boolean lostFocus, Boolean getFocus) {
						PayRollUtility
								.debug("============== eidLableFocusHandler Start========================");
						if (lostFocus) {
							try {
								String empId = employeeIDField.getText().trim();
								if (!empId.equals("")) {
									
									PayRollUtility.validateEmpId(empId);
									employee = employeeMgmt.getEmpById(empId);
									employeeNameField.setText(employee.getEmpName());
									populateLeaveTable(empId);
									
								}
							} catch (Exception exception) {
								employeeIDField.deselect();
								employeeIDField.clear();
								exception.printStackTrace();
								showError(exception.getMessage());
//								moveFocusToComp(employeeIDField);
							}
						}
						PayRollUtility
								.debug("============== eidLableFocusHandler END========================");
					}
				});
	}

	@Override
	// This method is called by the FXMLLoader when initialization is complete
	public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
		
		iniTableProps();
		eidLableFocusHandler();
		String year = String.valueOf(PayRollUtility.getYear());
		to_year.getSelectionModel().select(year);
		from_year.getSelectionModel().select(year);

		leaveTypeBox.getSelectionModel().selectedIndexProperty()
				.addListener(new ChangeListener<Number>() {

					@Override
					public void changed(ObservableValue arg0, Number oldNumber,
							Number newNumber) {
						try {
							if (newNumber.intValue() < 0)
								return;
							if (!validEmpId()) {
								leaveTypeBox.getSelectionModel()
										.clearSelection();
								return;
							}
							float balance = leaveDAO.getLeaveBalance(
									employee.getEmpId(), newNumber.intValue());
						} catch (Exception e) {
							showError(UIMessages.LEAVE_BALANCE_ERROR
									+ employee.getEmpId());
							refreshUI(null);
							return;
						}
					}

				});

		to_year.getSelectionModel().selectedIndexProperty()
				.addListener(new ChangeListener<Number>() {

					@Override
					public void changed(ObservableValue arg0, Number arg1,
							Number arg2) {

						to_month.getSelectionModel().clearSelection();
					}

				});
		from_year.getSelectionModel().selectedIndexProperty()
				.addListener(new ChangeListener<Number>() {

					@Override
					public void changed(ObservableValue arg0, Number arg1,
							Number arg2) {

						from_month.getSelectionModel().clearSelection();
					}
 
				});
		to_month.getSelectionModel().selectedIndexProperty()
				.addListener(new ChangeListener<Number>() {

					@Override
					public void changed(ObservableValue arg0, Number arg1,
							Number arg2) {

						to_date.getSelectionModel().clearSelection();
						to_date.getItems().clear();
						toMonthDaysList.clear();
						toMaxDay = PayRollUtility.getMaxDayofMonth(Integer
								.parseInt(to_year.getSelectionModel()
										.getSelectedItem()), to_month
								.getSelectionModel().getSelectedIndex());
						
						for (int i = 1; i <= toMaxDay; i++) {

							toMonthDaysList.add(i + "");
						}
						to_date.getItems().addAll(toMonthDaysList);
					}

				});
		from_month.getSelectionModel().selectedIndexProperty()
				.addListener(new ChangeListener<Number>() {

					@Override
					public void changed(ObservableValue arg0, Number arg1,
							Number arg2) {

						from_date.getSelectionModel().clearSelection();
						from_date.getItems().removeAll(fromMonthDaysList);
						fromMonthDaysList.clear();
						System.out.println(from_date.getItems());
						fromMaxDay = PayRollUtility.getMaxDayofMonth(Integer
								.parseInt(from_year.getSelectionModel()
										.getSelectedItem()), from_month
								.getSelectionModel().getSelectedIndex());
						for (int i = 1; i <= fromMaxDay; i++) {

							fromMonthDaysList.add(i + "");
						}
						from_date.getItems().addAll(fromMonthDaysList);

					}

				});

		to_date.getSelectionModel().selectedItemProperty()
				.addListener(new ChangeListener<String>() {

					@Override
					public void changed(ObservableValue arg0, String old,
							String newNum) {

						noOfDays.clear();
						toHalfDay.setSelected(false);

						if (to_date.getSelectionModel().getSelectedIndex() < 0) {
							return;
						}

						String ValidationMSG = getValidationMessage().trim();
						if (!ValidationMSG.equals("")
								&& !ValidationMSG
										.equals(UIMessages.LEAVE_REASON)) {
							showError(ValidationMSG);
							moveFocusToComp(to_date);
							return;
						}

						fromDate = from_date.getSelectionModel()
								.getSelectedItem()
								+ "-"
								+ (from_month.getSelectionModel()
										.getSelectedIndex() + 1)
								+ "-"
								+ from_year.getSelectionModel()
										.getSelectedItem();

						toDate = to_date.getSelectionModel().getSelectedItem()
								+ "-"
								+ (to_month.getSelectionModel()
										.getSelectedIndex() + 1) + "-"
								+ to_year.getSelectionModel().getSelectedItem();

						int diff = PayRollUtility.compareTwoDates(fromDate, toDate);
						if (diff > 0) {
							showError(UIMessages.TO_DATE_BEFORE_FROM_DATE);
							return;
						}
						double numberOfDays = PayRollUtility
								.noOfDaysBetweenTwoDates(fromDate, toDate);
						noOfDays.setText(String.valueOf(numberOfDays));
					}

				});
		
		from_date.getSelectionModel().selectedItemProperty()
		.addListener(new ChangeListener<String>() {

			@Override
			public void changed(ObservableValue arg0, String old,
					String newNum) {

//				noOfDays.clear();
				fromHalfDay.setSelected(false);
				to_date.getSelectionModel().clearSelection();

			}
		});
		
		fromHalfDay.selectedProperty().addListener(
				new ChangeListener<Boolean>() {
					public void changed(ObservableValue ov, Boolean old_val,
							Boolean new_val) {
						if (noOfDays.getText().trim().equals("")
								|| fromDate == null || toDate == null) {
							return;
						}

						double numberOfDays = Double.parseDouble(noOfDays
								.getText());
						if (fromHalfDay.isSelected()) {
							numberOfDays = numberOfDays - 0.5;
						} else {
							numberOfDays = numberOfDays + 0.5;
						}

						noOfDays.setText(String.valueOf(numberOfDays));

					}
				});

		toHalfDay.selectedProperty().addListener(new ChangeListener<Boolean>() {
			public void changed(ObservableValue ov, Boolean old_val,
					Boolean new_val) {
				if (noOfDays.getText().trim().equals("") || fromDate == null
						|| toDate == null) {
					return;
				}
				double numberOfDays = Double.parseDouble(noOfDays.getText());
				if (toHalfDay.isSelected()) {
					numberOfDays = numberOfDays - 0.5;
				} else {
					numberOfDays = numberOfDays + 0.5;
				}

				noOfDays.setText(String.valueOf(numberOfDays));
			}
		});

		noOfDays.setEditable(false);
	}

	private boolean validEmpId() {

		if (employee == null || employeeIDField.getText().trim().equals("")) {
			showInfo(UIMessages.EMPLOYEE_ID_VALIDATION_MESSAGE);
			moveFocusToComp(employeeIDField);
			return false;
		}
		return true;
	}

	private void populateLeaveTable(String empId) {

		if (empId == null || empId.trim().equals("")) {
			return;
		}
		PayRollUtility
				.debug("===================== populateLeaveTable start =====================");

		data.clear();
		try {
			ArrayList<Leave> leaveList = leaveDAO.getLeaveHistory(empId);
			System.out.println("leaveList : " + leaveList);
			if(leaveList == null){
				return;
			}
			data.addAll(LeaveDetail.getLeaveDetailList(leaveList));
		} catch (BusinessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		PayRollUtility.debug("data  : " + data);
		LeaveTable.setItems(data);

		PayRollUtility
				.debug("===================== populateLeaveTable end =====================");

	}

	private void iniTableProps() {
		LeaveTable.setEditable(true);

		LEAVE_TYPE.setCellValueFactory(new PropertyValueFactory<LeaveDetail, String>(
						"LEAVE_TYPE"));
		FROM_DATE
				.setCellValueFactory(new PropertyValueFactory<LeaveDetail, String>(
						"FROM_DATE"));

		TO_DATE.setCellValueFactory(new PropertyValueFactory<LeaveDetail, String>(
				"TO_DATE"));

		number.setCellValueFactory(new PropertyValueFactory<LeaveDetail, String>(
				"number"));

		Reason.setCellValueFactory(new PropertyValueFactory<LeaveDetail, String>(
				"Reason"));
	}
}
